package com.jiangyg.mall.core.support.restful;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.jiangyg.mall.core.enums.Operator;
import com.jiangyg.mall.core.utils.bean.BeanUtils;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import javax.validation.constraints.Max;
import java.io.Serializable;
import java.util.*;

@Data
@NoArgsConstructor
@EqualsAndHashCode
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({"current", "size", "total", "records"})
@JsonIgnoreProperties(allowSetters = true, value = {"orders", "criterias", "searchModel"})
public class Pagination<V> implements Serializable {

    private static final long serialVersionUID = 1126682170610781404L;

    /**
     * 查询数据列表
     */
    private List<V> records = null;

    /**
     * 总数
     */
    private long total = 0;

    /**
     * 每页显示条数，默认 10
     */
    @Max(100)
    private long size = 10;

    /**
     * 当前页
     */
    private long current = 1;

    @JsonProperty(value = "orders")
    private List<Order> orders;

    /**
     * 动态查询条件
     */
    @JsonProperty(value = "criterias")
    private List<Criteria> criterias;

    /**
     * 功能描述：根据属性名获取动态查询条件
     * <p>
     * 注意：未匹配到动态条件则抛出异常
     *
     * @param name 属性名
     * @return 返回动态查询条件
     */
    public Criteria obtainCriteriaByName(String name) {
        // TODO 未匹配到动态条件则抛出异常
        Criteria criteria = null;
        if (CollectionUtils.isNotEmpty(this.criterias)) {
            final Optional<Criteria> optional = this.criterias.stream().filter(c -> StringUtils.equals(c.getName(), name)).findFirst();
            if (optional.isPresent()) {
                criteria = optional.get();
            }
        }
        return criteria;
    }

    /**
     * 功能描述：动态查询条件转Map
     *
     * @return Map
     */
    public Map<String, Object> toSearchMap() {
        final Map<String, Object> searchMap = new HashMap<>();
        if (CollectionUtils.isEmpty(this.criterias)) {
            return searchMap;
        }
        for (Criteria criteria : this.criterias) {
            if (Operator.decide(criteria.getOperator()) == Operator.IN
                    || Operator.decide(criteria.getOperator()) == Operator.BT) {
                searchMap.put(criteria.getName(), criteria.getValues());
                continue;
            }
            searchMap.put(criteria.getName(), criteria.getValue());
        }
        return searchMap;
    }

    /**
     * 功能描述：动态查询条件转SearchModel
     *
     * @return SearchModel
     */
    public <S> S toSearchModel(Class<S> clazz) throws Exception {
        final S searchModel = clazz.newInstance();
        if (CollectionUtils.isEmpty(this.criterias)) {
            return searchModel;
        }
        for (Criteria criteria : this.criterias) {
            if (!BeanUtils.hasProperty(clazz, criteria.getName())) {
                continue;
            }
            if (Operator.decide(criteria.getOperator()) == Operator.IN
                    || Operator.decide(criteria.getOperator()) == Operator.BT) {
                BeanUtils.setProperty(searchModel, criteria.getName(), criteria.getValues());
                continue;
            }
            BeanUtils.setProperty(searchModel, criteria.getName(), criteria.getValue());
        }
        return searchModel;
    }

    public void addRecord(V t) {
        if (this.records == null) {
            this.records = new ArrayList<>();
        }
        this.records.add(t);
    }

}
